﻿using SBlogCore.WebAdminApplication.SysRoleManager.IServices;
using SBlogCore.Entitys.SysRoleManager;
using SBlogCore.Entitys.SystemManager;
using SBlogCore.Entitys.SysUserManager;
using SBlogCore.WebAdminApplication.SysRoleManager.Dto;
using SBlogCore.WebAdminApplication.SysManager.CacheServices;
using SBlogCore.Common.JWTExtend.Models;
using SBlogCore.WebAdminApplication.SysManager.IServices;

namespace SBlogCore.WebAdminApplication.SysRoleManager.Serivices
{
    public class SysRoleManagerService: ISysRoleManagerService
    {
        private readonly IRepository<SysRoleInfo> _sysRoleInfo;
        private readonly IRepository<SysUserRole> _sysUserRole;
        private readonly IRepository<SysUserInfo> _sysUserInfo;
        private readonly IMenuCacheService _menuCache;
        private readonly ISysMenuManagerService _sysMenuManagerService;
        private readonly IRepository<SysRoleMenu> _sysRoleMenu;

        public SysRoleManagerService(
            IRepository<SysRoleInfo> sysRoleInfo,
            IRepository<SysUserRole> sysUserRole,
            IRepository<SysRoleMenu> sysRoleMenu,
            IRepository<SysUserInfo> sysUserInfo,
            IMenuCacheService menuCache,
            ISysMenuManagerService sysMenuManagerService)
        {
            this._sysRoleInfo = sysRoleInfo;
            this._sysUserRole = sysUserRole;
            this._sysUserInfo = sysUserInfo;
            _menuCache = menuCache;
            _sysMenuManagerService = sysMenuManagerService;
            this._sysRoleMenu = sysRoleMenu;
        }
        /// <summary>
        /// 获取分页数据
        /// </summary>
        /// <returns></returns>
        public async Task<PageList<SysRoleInfo>> GetList(SysRoleInfoQueryInPut inPut)
        {
            Expression<Func<SysRoleInfo, bool>> expression = w => true;
            if (!string.IsNullOrEmpty(inPut.Name))
            {
                expression = expression.And(w => w.Name!.Contains(inPut.Name));
            }
            if (!string.IsNullOrEmpty(inPut.Code))
            {
                expression = expression.And(w =>w.Code!.Contains(inPut.Code));
            }
            var pageListList = await _sysRoleInfo.Where(expression).OrderBy(w=>w.Sort).ToPagedListAsync(inPut.PageIndex??1, inPut.PageSize??10);
            return pageListList;
        }

        /// <summary>
        /// 创建角色
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task Add(SysRoleInfoInPut inPut)
        {
            if (await AnyCode(inPut.Code!))
            {
                throw SBlogCoreException.Say($"编码{inPut.Code}已存在！");
            }

            var entity = inPut.Adapt<SysRoleInfo>();
            await _sysRoleInfo.InsertNowAsync(entity);
        }
        /// <summary>
        /// 修改数据
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task Upload(SysRoleInfoUploadInPut inPut)
        {
            if (await AnyCode(inPut.Code!, inPut.Id))
            {
                throw SBlogCoreException.Say($"编码{inPut.Code}已存在！");
            }
            var entity = await _sysRoleInfo.FirstOrDefaultAsync(w => w.Id == inPut.Id);
            if (entity==null)
            {
                throw SBlogCoreException.Say($"数据不存在！");
            }

            entity.Name = inPut.Name;
            entity.Code = inPut.Code;
            entity.Sort = inPut.Sort;
            entity.Remark = inPut.Remark;
            await _sysRoleInfo.UpdateNowAsync(entity);
        }
        /// <summary>
        /// 为角色添加用户
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task UpdateRoleUser(RoleUserInPut inPut)
        {
            //查询出已经有此权限的用户Id
            var ids = await _sysUserRole.Where(t => t.SysRoleId == inPut.RoleId && inPut.UserIds.Contains(t.SysUserId)).Select(t => t.SysUserId).ToListAsync();

            var users = inPut.UserIds.Where(t => !ids.Contains(t));

            var list = users.Select(t => new SysUserRole()
            {
                SysUserId = t,
                SysRoleId = inPut.RoleId
            }).ToList();
            //新增新实体映射
            await _sysUserRole.InsertRangeNowAsync(list);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 为角色移除用户
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task MoveRoleUser(RoleUserInPut inPut)
        {
            var data=await _sysUserRole.Where(w=>w.SysRoleId==inPut.RoleId&&inPut.UserIds.Contains(w.SysUserId)).ToListAsync();
            await _sysUserRole.DeleteRangeNowAsync(data);
            await _menuCache.ClearMenu();
        }

        /// <summary>
        /// 为用户修改角色
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task UpdateUserRole(UserRoleInPut inPut)
        {
            //查询出已经有此权限的用户Id
            var deleteList = await _sysUserRole.Where(t => t.SysUserId == inPut.UserId && !inPut.RoleIds.Contains(t.SysRoleId)).ToListAsync();
            await _sysUserRole.DeleteRangeNowAsync(deleteList);
            var ids = await _sysUserRole.Where(t => t.SysUserId == inPut.UserId && inPut.RoleIds.Contains(t.SysRoleId)).Select(t => t.SysRoleId).ToListAsync();
            var roles = inPut.RoleIds.Where(t => !ids.Contains(t));
            var list = roles.Select(t => new SysUserRole()
            {
                SysUserId = inPut.UserId,
                SysRoleId = t
            }).ToList();
            //新增新实体映射
            await _sysUserRole.InsertRangeNowAsync(list);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 为用户移除角色
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task MoveUserRole(UserRoleInPut inPut)
        {
            var data = await _sysUserRole.Where(w => w.SysRoleId == inPut.UserId && inPut.RoleIds.Contains(w.SysRoleId)).ToListAsync();
            await _sysUserRole.DeleteRangeNowAsync(data);
            await _menuCache.ClearMenu();
        }

        /// <summary>
        /// 获取所有拥有该权限的用户
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<List<SysUserRole>> GetUerListByRole(long id)
        {
            var data = await _sysUserRole
                .Where(w => w.SysRoleId == id)
                .Include(w=>w.SysUser)
                .ToListAsync();
            return data;
        }

        /// <summary>
        /// 通过权限ID获取所有用户，并标识该用户是否拥有该权限
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task<PageList<UserWithRoleOutPut>> GetUserInfoWithRole(UserInfoWithRoleQueryInPut inPut)
        {
            List<UserWithRoleOutPut> outPuts = new List<UserWithRoleOutPut>();
            var orgIdStr = inPut.OrgId.ToString();
            PageList<SysUserInfo> userList = await _sysUserInfo.DetachedEntities.Where(w => w.SysOrgInfo!.LineNode!.Contains(orgIdStr)).Include(w=>w.SysOrgInfo).ToPagedListAsync(inPut.PageIndex??1, inPut.PageSize??20);
            List<SysUserRole> roleList = await _sysUserRole.DetachedEntities.Where(w => w.SysRoleId == inPut.RoleId).ToListAsync();
            foreach (var user in userList.Items)
            {
                var anyRole = roleList.Any(w => w.SysUserId == user.Id);
                outPuts.Add(new UserWithRoleOutPut()
                {
                    UserId = user.Id,
                    UserName = user.UserName,
                    AnyRole = anyRole,
                    SysOrgName = user.SysOrgInfo?.Name
                });
            }
            PageList<UserWithRoleOutPut> pageList = new PageList<UserWithRoleOutPut>
            {
                Items = outPuts,
                PageIndex = userList.PageIndex,
                PageSize = userList.PageSize,
                TotalCount=userList.TotalCount
            };
            return pageList;
        }
        /// <summary>
        /// 通过用户ID获取所有权限，并标识该用户是否拥有某个权限
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns> 
        public async Task<List<long>> GetRoleWithUser(long userId)
        {
            var roleList = await _sysUserRole.Where(w => w.SysUserId == userId).ToListAsync();
            return roleList.Select(s => s.SysRoleId).ToList();
        }
        /// <summary>
        /// 删除
        /// </summary>
        /// <param name="ids"></param>
        /// <returns></returns>
        public async Task Delete(IEnumerable<long> ids)
        {
            var dataList =await _sysRoleInfo.Where(w => ids.Contains(w.Id)).ToListAsync();
            await _sysRoleInfo.DeleteRangeNowAsync(dataList);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 编码是否已存在
        /// </summary>
        /// <param name="code"></param>
        /// <param name="id"></param>
        /// <returns></returns>
        public async Task<bool> AnyCode(string code,long? id=null)
        {
            Expression<Func<SysRoleInfo, bool>> expression = w => w.Code == code ;
            if (id.HasValue)
            {
                expression = expression.And(w=> w.Id != id);
            }
            var res = await _sysRoleInfo.AnyAsync(expression);
            return res;
        }

        /// <summary>
        /// 获取当前菜单所匹配的角色
        /// </summary>
        /// <param name="menuId"></param>
        /// <returns></returns>
        public async Task<List<long>> GetRoleWithMenu(long menuId)
        {
            var roleMenus = await _sysRoleMenu.Where(w => w.SysMenuId == menuId).ToListAsync();
            return roleMenus.Select(s=>s.SysRoleId).ToList();
        }
        /// <summary>
        /// 为角色添加菜单
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>

        public async Task UpdateRoleWithMenu(RoleMenuInPut inPut)
        {
            //删除不存在的数据
            List<SysRoleMenu> deleteList = await _sysRoleMenu.Where(w => !inPut.MenuIds.Contains(w.SysMenuId)&&w.SysRoleId== inPut.RoleId).ToListAsync();
            await _sysRoleMenu.DeleteRangeNowAsync(deleteList);
            //加入新的数据
            List<long> anyHave = await _sysRoleMenu.Where(w => inPut.MenuIds.Contains(w.SysMenuId) && w.SysRoleId == inPut.RoleId).Select(s => s.SysMenuId).ToListAsync();
            IEnumerable<long> menuIds = inPut.MenuIds.Where(w => !anyHave.Contains(w));
            var newData = menuIds.Select(s => new SysRoleMenu()
            {
                SysMenuId = s,
                SysRoleId = inPut.RoleId
            });
            await _sysRoleMenu.InsertRangeNowAsync(newData);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 移除角色所拥有的的菜单
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task MoveRoleWithMenu(RoleMenuInPut inPut)
        {
            List<SysRoleMenu> list = await _sysRoleMenu.Where(w => inPut.MenuIds.Contains(w.SysMenuId)).ToListAsync();
            await _sysRoleMenu.DeleteRangeNowAsync(list);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 为角色添加菜单
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>

        public async Task UpdateMenuWithRole(MenuRoleInPut inPut)
        {
            //删除不存在的数据
            List<SysRoleMenu> deleteList = await _sysRoleMenu.Where(w => !inPut.RoleIds.Contains(w.SysRoleId)&&w.SysMenuId==inPut.MenuId).ToListAsync();
            await _sysRoleMenu.DeleteRangeNowAsync(deleteList);
            //插入新数据
            List<long> anyHave = await _sysRoleMenu.Where(w => inPut.RoleIds.Contains(w.SysRoleId)&&w.SysMenuId==inPut.MenuId).Select(s => s.SysRoleId).ToListAsync();
            IEnumerable<long> roleIds = inPut.RoleIds.Where(w => !anyHave.Contains(w));
            var newData = roleIds.Select(s => new SysRoleMenu()
            {
                SysRoleId = s,
                SysMenuId = inPut.MenuId
            });
            await _sysRoleMenu.InsertRangeNowAsync(newData);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 移除角色所拥有的的菜单
        /// </summary>
        /// <param name="inPut"></param>
        /// <returns></returns>
        public async Task MoveMenuWithRole(MenuRoleInPut inPut)
        {
            List<SysRoleMenu> list = await _sysRoleMenu.Where(w => inPut.RoleIds.Contains(w.SysRoleId)).ToListAsync();
            await _sysRoleMenu.DeleteRangeNowAsync(list);
            await _menuCache.ClearMenu();
        }
        /// <summary>
        /// 获取当前角色所拥有的菜单权限
        /// </summary>
        /// <param name="roleId"></param>
        /// <returns></returns>
        public async Task<List<long>> GetMenuWithRole(long roleId)
        {
            List<SysRoleMenu> data = await _sysRoleMenu.DetachedEntities.Where(w => w.SysRoleId == roleId&&!(w.SysMenu!.IsParent ?? false)).Include(w=>w.SysMenu).ToListAsync();
            return data.Select(s => s.SysMenuId).ToList();
        }
        /// <summary>
        /// 通过用户ID，获取该用户所拥有的菜单
        /// </summary>
        /// <param name="user"></param>
        /// <returns></returns>
        public async Task<List<SysMenu>> GetMenuWithUserRole(TokenModelJwt user)
        {
            var userId= user.Uid;
            var isAdmin = user.Role?.Split(',').Contains("Admin")??false;
            if (isAdmin)
            {
                var list = await _menuCache.GetOrCreateMenu("Admin", async () =>
                {
                    var res =await _sysMenuManagerService.GetMenuDataList();
                    return res;
                });
                return list!;
            }
            else
            {
                var list = await _menuCache.GetOrCreateMenu(userId.ToString(), async () =>
                {
                    var userInfo = await _sysUserRole.Where(w => w.SysUserId == userId)
                        .Include(w => w.SysRole)
                        .ThenInclude(w => w.SysMenus)
                        .ToListAsync();
                    var res = userInfo.Where(w => w.SysRole.SysMenus != null).SelectMany(s => s.SysRole.SysMenus!)
                        .Distinct().OrderBy(t => t.Order).Where(w => w.ParentInfoId == null).ToList();
                    return res;
                });
                return list!;
            }
        }
        /// <summary>
        /// 通过用户ID获取角色集
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public async Task<List<SysRoleInfo>?> GetRolesWithUser(long userId)
        {
            var userInfo = await _sysUserInfo.Where(w => w.Id == userId).Include(w => w.SysUserRoles).ThenInclude(w=>w.SysRole).FirstOrDefaultAsync();
            if (userInfo == null)
                throw SBlogCoreException.Say($"用户不存在！");
            List<SysRoleInfo> roles = userInfo.SysRoles;
            return roles;
        }
    }
}
